package srzy.module

import scala.actors._
import scala.actors.Actor._

abstract class BroadcastActor extends Actor {
  // can be set by external actor, therefore @volatile
  @volatile var isBroken = false
  private var canRun = true
  private var counter = 0L

  protected def broadcast(m: BSend) = {
    if (!isBroken) {
      for (a <- m.recipients) a ! BDeliver(m.data)
    } else if (canRun) {
      canRun = false // simulate it being broken
      for (a <- m.recipients.take(2)) a ! BDeliver(m.data)
      println("error at " + this)
    }
  }
  // to be overridden in subtraits
  protected def reaction: PartialFunction[Any, Unit] = {
    case BCast(msg, recipients) =>
      counter += 1
      broadcast(BSend(msg, recipients, counter))
    case 'stop =>
      exit()
  }

  def act = loopWhile(canRun) { react(reaction) }
}

case class BCast(data: Any, recipients: Set[Actor])

case class BSend(data: Any, recipients: Set[Actor],
  timestamp: Long)

case class BDeliver(data: Any)